// https://juejin.cn/post/6981728323051192357
// 该篇文章，多数为基础内容，取掘金jsp中没有的内容，记录
// 同时，该篇文章的文末，文献链接丰富

// //  交叉&类型
// interface Waiter {
//   anjiao: boolean;
//   say: () => {};
// }
// interface Teacher {
//   anjiao: boolean;
//   skill: () => {};
// }
// // 类似于，合并两个类型
// function judgeWho2(jishi: Waiter & Teacher) {}
// judgeWho2({
//   say(): any {
//     console.log("say");
//   },
//   anjiao: false,
//   skill(): any {
//     console.log("skill");
//   },
// });

// // keyof，
// // 作用：获取属性名的集合（如果是class则，只抽取public类型的属性名）
// class Point {
//   x: number;
//   protected y: string;
//   private z: boolean;
//   c: string;
// }
// // 用法一：转换成联合类型
// type V = keyof Point;
// let v: Point[V];
// // 用法：使用extends方法，将属性约束在这个集合内
// function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
//   return o[name];
// }
// console.log(get({ a: "aa", b: "bb" }, "b"));

// Utility Types： ts封装的工具类型;

export interface UserModel {
  name: string;
  age?: number;
  sex: number;
}

// 1、Partial<T>
// 将T中所有属性转换为可选属性
type JUserModel = Partial<UserModel>;

// 2、Required<T>
// 将T中所有属性转换为必选属性
type JUserModel2 = Required<UserModel>;

// 3、Readonly<T>
// 将T中所有属性设置为只读
type JUserModel3 = Readonly<UserModel>;

// 4、Record<K,T>
// 使用属性名的集合/类型，生成具有相同属性值类型的新类型
// 第一参：属性名的集合 / 属性名的类型
// 第二参：属性值的类型
type keyNames = "name" | "age";
interface IGirl {
  name: string;
  age: number;
}
type Todo1 = Record<keyNames, string>;
type Todo2 = Record<keyof IGirl, string>;
type allGirls = Record<string, IGirl>;

// 5、Pick<T,K>
// 挑选类型中的部分属性，生成一个新的类型
interface Todo {
  title: string;
  description: string;
  done: boolean;
}
type TodoBase = Pick<Todo, "title" | "done">;

// 6、Omit<T,K>
// 排除类型中的部分属性，生成一个新的类型
type TodoBase1 = Omit<Todo, "title" | "done">;

// 7、Exclude<T,U>
// 排除属性名集合中的部分属性名，生成一个新的属性名集合
type T0 = Exclude<"a" | "b" | "c", "a">;

// 8、Extract<T,U>
// 获取属性名集合中的部分属性名，生成一个新的属性名集合
type T1 = Extract<"a" | "b" | "c", "b" | "c">;

// 9、NonNullable<T>
// 排除属性名集合中的 null undefined，生成一个新的属性名集合
interface nonNull {
  postion: string;
}
type nonNullType = NonNullable<null | undefined | "postion">;
let nonNullValue: nonNull[nonNullType] = "gz";
// console.log(nonNullValue);

// 10、Parameters<T>
// 获取函数的所有参数类型，生成一个类型数组
type F0 = Parameters<(s: string, n: number) => string>;
let arr1: F0 = ["Q", 3];
function f1([s, n]: F0) {
  console.log("s----", s);
  console.log("n----", n);
}
// f1(["a", 1]);

// 11、ReturnType<T>
// 获取函数的返回类型
type FR = ReturnType<() => string>;
let FR = "FR";

// 12、InstanceType<Type>
// 官方解释：由构造函数类型Type的实例类型，来构建一个新类型
//（https://github.com/zhongsp/TypeScript/blob/dev/zh/reference/utility-types.md#instancetypetype）
// 个人理解：配合typelf，获取class的类型
class FI {
  name: string;
}
type TC = InstanceType<typeof FI>;

let tc: FI = {
  name: "bb",
};

// 以上是文档中提炼的内容
// 后续学习资料还没看
